iT邦幫忙

2026 iThome 鐵人賽

DAY 1
0
Software Development

GPU 效能優化實戰:30 天從 Kernel 到 Profiling (重賽版)系列 第 1

Day 1:所以,蝦米是「優化」? (重賽版 )

  • 分享至 

  • xImage
  •  

因為耍笨忘記發文所以中斷ㄌ...
還雷到團體賽的隊友...10分有11分的抱歉
https://ithelp.ithome.com.tw/upload/images/20260821/20183597tO7yTf65uh.png
但聽說重賽完成還是可以拿獎牌....
https://ithelp.ithome.com.tw/upload/images/20260821/201835973Bo9ibRA9t.png

想說 不寫白不寫 不然 就...

所以來ㄌ個重賽版

基本上跟原本的一樣 但我會每天搬運過來
或許會有一些不一樣 譬如說多了幾張來自派星機的梗圖

圓規正轉

所以,蝦米是優化?

首先,蝦米是優化?

假設今天我們手上有一個 Kernel、一個程式,或者 whatever,反正我們現在只知道一件事情:它跑了 100 ms。

但 100 ms 到底是快還是慢?其實不知道。因為我們不知道它跑在什麼硬體上、不知道 input size,也不知道同樣的事情別人需要花多少時間。現在的 100 ms 就只是一個測量結果而已,它自己並不能告訴我們效能到底好不好。

所以要談優化,第一件事情其實很簡單:你需要一個比較的對象。

假設同樣的運算、同樣的 input、同樣的硬體,我們有另外一個版本只需要 50 ms,那事情就開始有意思了。100 ms 跟 50 ms 放在一起,我們終於可以說後者有 2x speedup,或者換個角度說,它的 execution time 減少了 50%。

這個比較對象可以是修改之前的版本,可以是另一套 implementation,也可以是某個我們估算出來的硬體上限。後面我們甚至會開始從算力、Memory Bandwidth 這些東西去估:「這個 Kernel 理論上到底還能快多少?」但不管是哪一種,背後其實都是同一件事:

有比較,才有優化。

沒有 Baseline 的 100 ms,不是快,也不是慢。它就只是 100 ms。

不過,有了 Baseline,也不代表看到哪裡可以變快就要衝過去改。

假設今天整個程式跑完需要 100 ms,其中 Program A 花了 80 ms,Program B 花了 20 ms。你看了一下 Program B,覺得這東西寫得有夠爛,改一改應該可以直接快兩倍。

然後你真的做到了:

Program A: 80 ms
Program B: 20 ms → 10 ms

Program B 快了整整 2x,execution time 直接少了一半,單看這個結果其實很漂亮。但放回整個程式:

Before: 80 + 20 = 100 ms
After:  80 + 10 =  90 ms

你花了很多力氣把一段程式優化了 2x,最後 End-to-End 只從 100 ms 變成 90 ms,大概是 1.11x speedup

這就是效能優化裡一個很現實的問題:一個東西「能優化多少」,跟它「值不值得優化」,其實是兩件不同的事情。

如果一段程式只佔整體執行時間的 20%,那就算你有一天突然得到神力,把它從 20 ms 直接優化成 0 ms,剩下那 80 ms 還是好端端地站在那裡。所以整個程式最快也只能:

100 ms → 80 ms

也就是最多 1.25x

這件事情其實就是 Amdahl's Law 在講的東西。假設可以被加速的部分佔原本執行時間的比例是 (P),而我們把這部分加速了 (S) 倍,那整體的 Speedup 會是:

Amdahl's Law

這個公式真正想講的事情很簡單:你沒有動到的那部分,最後會變成你的極限。

https://ithelp.ithome.com.tw/upload/images/20260821/20183597g3GF6D0idI.jpg
出處
所以比起看到哪段 Code 很醜就先救哪段,我們更在意的是時間到底花在哪裡。如果一個 Kernel 只佔整個程式的 1%,就算把它優化得跟鬼一樣,對整體效能可能還是沒什麼影響;反過來,一個 Kernel 佔了 70% 的時間,就算最後只能快個 20%,搞不好都比前面那個有價值得多。

簡單來說就是:

先找大頭。

不然很容易忙了一整天,Benchmark 也真的變快了,最後一看 End-to-End:

「嗯?」

「大的勒?」

那時間到底花去哪了?

找到大頭之後,接下來才是比較麻煩的地方。

一個 Kernel 跑了 10 ms,而且佔整個程式 70% 的時間,我們現在知道它很重要,卻還是不知道這 10 ms 到底花去哪裡。這也是為什麼「慢」本身其實沒有告訴我們該怎麼優化。

這邊先不急著看一大堆 GPU Metrics,也先不管 Warp、Occupancy、Cache、Register。那些後面都會慢慢遇到。我們現在先很粗暴地把時間切成三個方向:

Compute、Memory、Overhead。

有些工作是真的需要做很多計算,資料都準備好了,GPU 的計算單元也一直在工作,但就是還有一大堆東西沒算完。這種我們先叫它 Compute Bound

另一種剛好相反。計算本身可能根本沒多少,GPU 一下就算完了,時間反而花在把資料搬進來、搬出去。這種比較接近 Memory Bound

最後還有一種比較尷尬:Kernel 本身可能都很快,但工作切得太碎,每次都要 Launch、Dispatch、Synchronization,最後「叫 GPU 去工作」這件事情本身開始變得不能忽略。這種我們先放進 Overhead Bound

這三種情況可以先想成一間工廠:

Compute、Memory 與 Overhead 的工廠示意圖

Memory 負責把原料送進來,Compute 是工廠裡真正加工東西的機器,而 Overhead 則是每次開工以前要處理的那些事情。

如果今天原料一直送不進來,那把工廠裡的機器換成兩倍快,大概也沒什麼用。反過來,如果原料早就堆滿整間工廠,現在是機器真的做不完,那再買十台卡車來送貨,也不會讓成品生得比較快。

至於如果工廠每做一顆螺絲就關門一次,下一顆螺絲來了再重新開門、打卡、開機……

那工廠跟卡車可能都沒有問題。

是你的開工方式很有問題。

後面會看到的 Memory Bandwidth、Tensor Core、Kernel Fusion、Shared Memory,甚至 PTX,其實都不是「用了就會變快」的魔法。它們各自在處理不同的限制。

所以比起先問「CUDA 有哪些優化技巧」,我們現在比較想知道的是:

到底是什麼東西,限制了它繼續變快?


下一篇
Day 2|走進一顆 GPU:Thread、Warp、Block 到底都在做什麼? (重賽版 )
系列文
GPU 效能優化實戰:30 天從 Kernel 到 Profiling (重賽版)2
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言